import _ from 'lodash'
import Vue from 'vue'
// import API from 'app/api'
import { Tab, TabGroup } from './model'
import * as Getters from './getters.js'

// 变动名称
const tabCreateGroup = 'tabCreateGroup'
const tabCreate = 'tabCreate'
const tabCreateInGroup = 'tabCreateInGroup'
const tabActivate = 'tabActivate'
const tabUpdate = 'tabUpdate'
const tabRemove = 'tabRemove'
const tabRemoveOther = 'tabRemoveOther'
const tabRemoveAll = 'tabRemoveAll'
const contextMenuOpen = 'contextMenuOpen'
const contextMenuClose = 'contextMenuClose'

const _activateTabGroup = (state, tabGroup) => {
  if (!Getters.isActive(state, tabGroup)) {
    state.activeTabGroupId = tabGroup.id
  }
}

const _activateTab = (state, tab) => {
  if (tab) {
    const tabGroup = Getters.getTabGroupOfTab(state, tab)
    if (Getters.isActive(state, tab) && Getters.isActive(state, tabGroup)) {
      return
    }
    Vue.set(state.tabGroups[tabGroup.id], 'activeTabId', tab.id)
    _activateTabGroup(state, tabGroup)
  }
}

const _createTabInGroup = (state, tabConfig, tabGroup) => {
  tabGroup = state.tabGroups[tabGroup.id]
  const newTab = Tab({
    id: _.uniqueId('tab_'),
    tabGroupId: tabGroup.id,
    ...tabConfig
  })
  Vue.set(state.tabs, [newTab.id], newTab)
  let tabIds = state.tabGroups[tabGroup.id].tabIds
  tabIds.push(newTab.id)
  Vue.set(state.tabGroups[tabGroup.id], 'tabIds', tabIds)
  _activateTab(state, newTab)
}

const _removeTab = (state, tab) => {
  if (Getters.isActive(state, tab)) { /* activateNextTab */
    let nextTab = Getters.getNextSiblingOfTab(state, tab)
    if (nextTab) {
      _activateTab(state, nextTab)
    }
  }

  let tabIds = state.tabGroups[tab.tabGroupId].tabIds
  tabIds.splice(tabIds.indexOf(tab.id), 1)
  state.tabGroups[tab.tabGroupId].tabIds = tabIds
  Vue.delete(state.tabs, tab.id)
}

export default {
  namespaced: true,
  state: {
    tabGroups: {},
    tabs: {},
    activeTabGroupId: '',
    contextMenu: {
      isActive: false,
      pos: { x: 0, y: 0 },
      contextNode: null
    }
  },
  getters: Getters,
  mutations: {
    [tabCreateGroup]: (state, { groupId, defaultContentType }) => {
      const newTabGroup = TabGroup({ id: groupId, type: defaultContentType })
      Vue.set(state.tabGroups, [newTabGroup.id], newTabGroup)
      _activateTabGroup(state, newTabGroup)
    },
    [tabCreate]: (state, tabConfig) => {
      let tabs = Getters.getTabsByPath(state, tabConfig.path)
      if (tabs.length > 0) {
        _activateTab(state, tabs[0])
      } else {
        // here we try our best to put the tab into the right group
        // first we try the current active group, check if it's of same type
        // if not, we try to find the group of same type as tab,
        // if can find none, well, we fallback to the current active group we found
        let tabGroup = Getters.getActiveTabGroup(state)
        if (tabGroup.type !== tabConfig.type) {
          let _tabGroup = _(state.tabGroups).find(g => g.type === tabConfig.type)
          if (_tabGroup) tabGroup = _tabGroup
        }
        _createTabInGroup(state, tabConfig, tabGroup)
      }
    },
    [tabCreateInGroup]: (state, [groupId, tabConfig]) => {
      let tabGroup = state.tabGroups[groupId]
      _createTabInGroup(state, tabConfig, tabGroup)
    },
    [tabActivate]: (state, tabId) => {
      const tab = state.tabs[tabId]
      _activateTab(state, tab)
    },
    [tabUpdate]: (state, tabConfig) => {
      const tab = state.tabs[tabConfig.id]
      if (tab) {
        let newTab = { ...tab, ...tabConfig }
        Vue.set(state.tabs, [tab.id], newTab)
      }
    },
    [tabRemove]: (state, tabId) => {
      const tab = state.tabs[tabId]
      _removeTab(state, tab)
    },
    [tabRemoveOther]: (state, tabId) => {
      const tab = state.tabs[tabId]
      _activateTab(state, tab)
      let tabGroup = state.tabGroups[tab.tabGroupId]
      const tabIdsToBeDeleted = _.without(tabGroup.tabIds, tab.id)
      const nextTabs = _.omit(state.tabs, tabIdsToBeDeleted)
      Vue.set(state.tabGroups[tabGroup.id], 'tabIds', [tab.id])
      state.tabs = nextTabs
    },
    [tabRemoveAll]: (state, tabId) => {
      const tab = state.tabs[tabId]
      const tabGroup = state.tabGroups[tab.tabGroupId]
      const tabIdsToBeDeleted = tabGroup.tabIds
      const nextTabs = _.omit(state.tabs, tabIdsToBeDeleted)
      Vue.set(state.tabGroups[tabGroup.id], 'tabIds', [])
      state.tabs = nextTabs
    },

    [contextMenuOpen]: (state, [pos, tab]) => {
      let contextMenu = {
        pos,
        contextNode: tab,
        isActive: true,
        tabGroupId: tab.tabGroupId
      }
      state.contextMenu = contextMenu
    },
    [contextMenuClose]: (state) => {
      state.contextMenu.isActive = false
    }
  },

  actions: {
    // initializeFileTree({ commit }) {
    // },
    // openFileNode({ commit }, [node, shouldBeFolded = null, deep = false]) {
    // }
  }
}
